
local alien = require "alien"
local alienex = require "alienex"
local config = require "config"
local max
    = math.max
local print, pairs
    = print, pairs


module(...)


local lib = alien.load(config.avbin_path)

local Result = 'int'
RESULT_ERROR = -1
RESULT_OK = 0

local StreamType = 'int'
STREAM_TYPE_UNKNOWN = 0
STREAM_TYPE_VIDEO = 1
STREAM_TYPE_AUDIO = 2

local SampleFormat = 'int'
SAMPLE_FORMAT_U8 = 0
SAMPLE_FORMAT_S16 = 1
SAMPLE_FORMAT_S24 = 2
SAMPLE_FORMAT_S32 = 3
SAMPLE_FORMAT_FLOAT = 4

local LogLevel = 'int'
LOG_QUIET = -8
LOG_PANIC = 0
LOG_FATAL = 8
LOG_ERROR = 16
LOG_WARNING = 24
LOG_INFO = 32
LOG_VERBOSE = 40
LOG_DEBUG = 48

local Timestamp = 'double' -- 'long'

FileInfo = alien.defstruct{
  {"structure_size", alienex.size_t};
  {"n_streams", "int"};
  {"start_time", Timestamp};
  {"duration", Timestamp};
  --[[
  char title[512];
  char author[512];
  char copyright[512];
  char comment[512];
  char album[512];
  int year;
  int track;
  char genre[32];
  --]]
}
FileInfo.size = FileInfo.size + (512 * 5) + 8 + 8 + 32
print(FileInfo.size)

StreamInfo_video = alien.defstruct{
  {"structure_size", alienex.size_t};
  {"type", StreamType};
  {"video_width", "int"};
  {"video_height", "int"};
  {"video_sample_aspect_num", "uint"};
  {"video_sample_aspect_den", "uint"};
}
StreamInfo_audio = alien.defstruct{
  {"structure_size", alienex.size_t};
  {"type", StreamType};
  {"audio_sample_format", SampleFormat};
  {"audio_sample_rate", "uint"};
  {"audio_sample_bits", "uint"};
  {"audio_channels", "uint"};
}
local maxsize = max(StreamInfo_video.size, StreamInfo_audio.size)
StreamInfo_video.size, StreamInfo_audio.size = maxsize, maxsize

Packet = alien.defstruct{
  {"structure_size", alienex.size_t};
  {"timestamp", Timestamp};
  {"stream_index", "int"};
  {"data", "pointer" --[[uint8_t*]]};
  {"size", alienex.size_t};
}

LogCallback_types = { ret="void"; "string" --[[module]], LogLevel, "string" --[[message]] }

local function Func(name, types)
  local func = lib["avbin_"..name]
  func:types(types)
  _M[name] = func
  return func
end

Func("get_version", { ret="int" })
Func("get_ffmpeg_revision", { ret="int" })
Func("get_audio_buffer_size", { ret=alienex.size_t })
Func("have_feature", { ret="int"; "string" })
Func("init", { ret=Result })
Func("set_log_level", { ret=Result; LogLevel })
Func("set_log_callback", { ret=Result; "callback" --[[LogCallback]] })
Func("open_filename", { ret="pointer" --[[File*]]; "string" })
Func("close_file", { ret="void"; "pointer" --[[File*]] })
Func("seek_file", { ret=Result; "pointer" --[[File*]], Timestamp })
Func("file_info", { ret=Result; "pointer" --[[File*]], "pointer" --[[FileInfo*]] })
Func("stream_info", { ret=Result; "pointer" --[[File*]], "int" --[[stream_index]], "pointer" --[[StreamInfo*]] })
Func("open_stream", { ret="pointer" --[[Stream*]]; "pointer" --[[File*]], "int" --[[stream_index]] })
Func("close_stream", { ret="void"; "pointer" --[[Stream*]] })
Func("read", { ret=Result; "pointer" --[[File*]], "pointer" --[[Packet*]] })
Func("decode_audio", { ret="int";
  "pointer" --[[Stream*]], "pointer" --[[uint8_t* data_in]], alienex.size_t --[[size_in]],
  "pointer" --[[uint8_t* data_out]], "ref int" --[[size_out]] })
Func("decode_video", { ret="int";
  "pointer" --[[Stream*]], "pointer" --[[uint8_t* data_in]], alienex.size_t --[[size_in]], "pointer" --[[uint8_t* data_out]]})
